"""Emoji and special character processor"""

from typing import Dict, Any, Optional
import emoji
import unicodedata
import re
import logging

from .base_cleaner import BaseCleaner

logger = logging.getLogger(__name__)


class EmojiProcessor(BaseCleaner):
    """Processor for handling emojis and special characters
    
    Can convert emojis to text descriptions or remove them entirely
    """
    
    def __init__(self, config: Optional[Dict[str, Any]] = None):
        """Initialize emoji processor
        
        Args:
            config: Configuration with options:
                - mode: 'remove', 'demojize', or 'keep' (default: 'demojize')
                - normalize_unicode: Whether to normalize unicode (default: True)
                - remove_zero_width: Whether to remove zero-width chars (default: True)
        """
        super().__init__(config)
        self.mode = self.config.get('mode', 'demojize')
        self.normalize_unicode = self.config.get('normalize_unicode', True)
        self.remove_zero_width = self.config.get('remove_zero_width', True)
        
        # Zero-width and invisible characters
        self.zero_width_chars = [
            '\u200b',  # Zero-width space
            '\u200c',  # Zero-width non-joiner
            '\u200d',  # Zero-width joiner
            '\u2060',  # Word joiner
            '\ufeff',  # Zero-width non-breaking space
            '\u180e',  # Mongolian vowel separator
            '\u2000',  # En quad
            '\u2001',  # Em quad
            '\u2002',  # En space
            '\u2003',  # Em space
            '\u2004',  # Three-per-em space
            '\u2005',  # Four-per-em space
            '\u2006',  # Six-per-em space
            '\u2007',  # Figure space
            '\u2008',  # Punctuation space
            '\u2009',  # Thin space
            '\u200a',  # Hair space
        ]
    
    def clean(self, data: Dict[str, Any]) -> Dict[str, Any]:
        """Process emojis and special characters in the data
        
        Args:
            data: Input data dictionary
            
        Returns:
            Data with processed emojis and special characters
        """
        # Process title
        if 'title' in data and data['title']:
            data['title'] = self._process_text(data['title'])
        
        # Process content
        if 'content' in data and data['content']:
            if isinstance(data['content'], str):
                data['content'] = self._process_text(data['content'])
            elif isinstance(data['content'], dict):
                for key, value in data['content'].items():
                    if isinstance(value, str):
                        data['content'][key] = self._process_text(value)
                    elif isinstance(value, list):
                        # Handle comments or other list fields
                        data['content'][key] = [
                            self._process_text(item) if isinstance(item, str) else item
                            for item in value
                        ]
        
        # Process description
        if 'description' in data and data['description']:
            data['description'] = self._process_text(data['description'])
        
        # Process excerpt
        if 'excerpt' in data and data['excerpt']:
            data['excerpt'] = self._process_text(data['excerpt'])
        
        return data
    
    def _process_text(self, text: str) -> str:
        """Process emojis and special characters in text
        
        Args:
            text: Text to process
            
        Returns:
            Processed text
        """
        if not text:
            return text
        
        try:
            # Remove zero-width characters first
            if self.remove_zero_width:
                text = self._remove_zero_width_chars(text)
            
            # Process emojis based on mode
            if self.mode == 'remove':
                text = self._remove_emojis(text)
            elif self.mode == 'demojize':
                text = self._demojize_text(text)
            # 'keep' mode doesn't modify emojis
            
            # Normalize unicode if configured
            if self.normalize_unicode:
                text = self._normalize_unicode_text(text)
            
            # Convert fullwidth characters to halfwidth
            text = self._convert_fullwidth_to_halfwidth(text)
            
            return text.strip()
            
        except Exception as e:
            logger.error(f"Error processing text: {e}")
            return text
    
    def _remove_zero_width_chars(self, text: str) -> str:
        """Remove zero-width and invisible characters
        
        Args:
            text: Text to clean
            
        Returns:
            Text without zero-width characters
        """
        for char in self.zero_width_chars:
            text = text.replace(char, '')
        
        # Remove other invisible control characters
        text = ''.join(char for char in text if unicodedata.category(char)[0] != 'C' or char in '\n\r\t')
        
        return text
    
    def _remove_emojis(self, text: str) -> str:
        """Remove all emojis from text
        
        Args:
            text: Text to clean
            
        Returns:
            Text without emojis
        """
        return emoji.replace_emoji(text, replace='')
    
    def _demojize_text(self, text: str) -> str:
        """Convert emojis to text descriptions
        
        Args:
            text: Text with emojis
            
        Returns:
            Text with emoji descriptions
        """
        # Convert emojis to :emoji_name: format
        text = emoji.demojize(text, delimiters=(' [', '] '))
        
        # Clean up the formatting
        text = re.sub(r'\s+\[', ' [', text)
        text = re.sub(r'\]\s+', '] ', text)
        text = re.sub(r'\s+', ' ', text)
        
        return text
    
    def _normalize_unicode_text(self, text: str) -> str:
        """Normalize unicode text
        
        Args:
            text: Text to normalize
            
        Returns:
            Normalized text
        """
        # Normalize to NFC (Canonical Decomposition, followed by Canonical Composition)
        text = unicodedata.normalize('NFC', text)
        
        # Replace common unicode punctuation with ASCII equivalents
        replacements = {
            '"': '"',  # Left double quotation mark
            '"': '"',  # Right double quotation mark
            ''': "'",  # Left single quotation mark
            ''': "'",  # Right single quotation mark
            '…': '...',  # Horizontal ellipsis
            '—': '-',  # Em dash
            '–': '-',  # En dash
            '•': '*',  # Bullet
            '°': ' degrees',  # Degree sign
            '™': ' TM',  # Trademark
            '®': ' (R)',  # Registered
            '©': ' (C)',  # Copyright
            '×': 'x',  # Multiplication sign
            '÷': '/',  # Division sign
        }
        
        for unicode_char, ascii_char in replacements.items():
            text = text.replace(unicode_char, ascii_char)
        
        return text
    
    def _convert_fullwidth_to_halfwidth(self, text: str) -> str:
        """Convert fullwidth characters to halfwidth
        
        Args:
            text: Text with potential fullwidth characters
            
        Returns:
            Text with halfwidth characters
        """
        # Convert fullwidth ASCII characters (０-９, Ａ-Ｚ, ａ-ｚ)
        result = []
        for char in text:
            code = ord(char)
            # Fullwidth ASCII variants
            if 0xFF01 <= code <= 0xFF5E:
                # Convert to normal ASCII
                result.append(chr(code - 0xFEE0))
            # Fullwidth space
            elif code == 0x3000:
                result.append(' ')
            else:
                result.append(char)
        
        return ''.join(result)